import React, { useState, useEffect } from "react"
import { useSafeAreaInsetsStyle } from "../../utils/useSafeAreaInsetsStyle"
import {
  View,
  ViewStyle,
  Text,
  ScrollView,
  SectionList,
  TouchableOpacity,
  ActivityIndicator,
} from "react-native"
import Animated, { Easing, FadeIn, FadeOut } from "react-native-reanimated"
import DatePicker from "react-native-date-picker"
import dayjs from "dayjs"
import { useNavigation } from "@react-navigation/native"
import { scale } from "react-native-size-matters"
import { useAppDispatch, useAppSelector } from "app/redux/hooks"

//Icons
import { AntDesign } from "@expo/vector-icons"
import { Ionicons } from "@expo/vector-icons"

//Local Component imports
import { colors } from "app/theme"
import MainHeader from "app/components/MainHeader"
import { Button } from "app/components"
import { styles } from "./styles"
import { DropdownComponent, EmptyComponent } from "app/components/DropDownComponent"
import { SelectOptionButton } from "app/components/SelectableOption"
import AppointmentRepeatView from "./AppointmentRepeatView"

//function imports
import {
  setRoom,
  setError,
  setRoomCost,
  setEtheraRooms,
  setDateCheckBox,
  setSelectedDates,
  setNumberOfWeeks,
  setBookingEndTime,
  setOtherLocations,
  setWeeklyCheckBox,
  setWeeklyRepeatGap,
  setAppointmentDate,
  setEtheraLocations,
  setBookingStartTime,
  setAppointmentLocation,
  resetAppointmentLocationScreen,
} from "app/redux/slices/createAppointmentSlice"
import {
  getEtheraRooms,
  getOtherLocations,
  getEtheraLocations,
  getRoomCost,
} from "app/services/apis/location"
import {
  generateGetRoomsBody,
  generateRoomCostBody,
} from "app/services/helperFunctions/generateBody"
import { setLoader, setLocationLoader } from "app/redux/slices/loadingSlice"
import MakeLocationData from "./LocationData"

export const AddAppointment = () => {
  const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom", "top"])

  //Hooks
  const navigation = useNavigation()
  const dispatch = useAppDispatch()

  //Local States
  const [date, setDate] = useState(new Date())
  const [locationDropdown, setLocationDropdown] = React.useState(false)
  const [dates, setDates] = useState({
    show: false,
    type: "",
    date: "",
    start: "",
    end: "",
  })

  const minTime = new Date()
  minTime.setHours(9)
  minTime.setMinutes(0)

  const maxTime = new Date()
  maxTime.setHours(10)
  maxTime.setMinutes(0)

  // This state is used to store the start time as a raw , nonFormatted time string,
  // ensuring that the minimum end time will always be greater than the start time in appointment Location screen
  const [minimumTime, setMinimunTime] = useState(minTime)
  const [maximumTime, setMaximumTime] = useState(maxTime)

  //retriving appointment state time , date and location etc
  const appointmentState = useAppSelector((state) => state?.createAppointment)
  const loadingState = useAppSelector((state) => state?.loading)

  //retriving current user details
  const providerState = useAppSelector((state) => state?.provider)

  const onPressWeekCheckBox = (newValue: any) => {
    dispatch(setWeeklyCheckBox(newValue))
  }

  const onPressDateCheckBox = (newValue: any) => {
    dispatch(setDateCheckBox(newValue))
  }

  const onPressRepeat = (number_of_weeks) => {
    dispatch(setNumberOfWeeks({ number_of_weeks }))
  }

  const onPressRepeatGap = (weeklyRepeatGap) => {
    dispatch(setWeeklyRepeatGap({ weeklyRepeatGap }))
  }

  const onSelectDates = (date) => {
    dispatch(setSelectedDates({ date }))
  }

  const onPressLocation = (item) => {
    dispatch(setAppointmentLocation(item))
    dispatch(setRoomCost("0:00"))
    setLocationDropdown(!locationDropdown)
    // in case user change its location from other to ethera after pressing weeklyRepeat then weeklyrepeat should be reset
    dispatch(setWeeklyCheckBox(false))
  }

  const onNextPress = () => {
    //To reset weeklyReapetGap and selected Dates In case User select and deselect weekly or date checkbox
    if (!appointmentState?.weeklyCheckbox && !appointmentState?.dateCheckBox) {
      //TODO reset selected dates too
      dispatch(setWeeklyRepeatGap({ weeklyRepeatGap: null }))
      dispatch(setNumberOfWeeks({ number_of_weeks: null }))
    }

    if (appointmentState?.appointmentLocationType !== "ethera") {
      if (
        !appointmentState?.appointmentLocation ||
        !appointmentState?.appointmentDate ||
        (appointmentState?.weeklyCheckbox &&
          (!appointmentState?.weeklyRepeatGap || !appointmentState?.number_of_weeks))
      ) {
        dispatch(setError("is required"))
        return
      } else {
        dispatch(setError(""))
        // @ts-ignore
        navigation.navigate("AppointmentDetails", {
          minimumTime: minimumTime,
          maximumTime: maximumTime,
        })
      }
    } else if (appointmentState?.appointmentLocationType === "ethera") {
      if (
        !appointmentState?.appointmentLocation ||
        !appointmentState?.appointmentDate ||
        !appointmentState?.room ||
        !appointmentState?.bookingStartTime ||
        !appointmentState?.bookingEndTime
      ) {
        dispatch(setError("is required"))
        return
      } else {
        dispatch(setError(""))
        // @ts-ignore
        navigation.navigate("AppointmentDetails", {
          minimumTime: minimumTime,
          maximumTime: maximumTime,
        })
      }
    }
  }

  //Fetching ETHERA LOCATOINS to populate location dropdown
  useEffect(() => {
    dispatch(setLocationLoader(true))
    getEtheraLocations()
      .then((result: any) => {
        dispatch(setLocationLoader(false))
        dispatch(setEtheraLocations(result?.data))
      })
      .catch((error: any) => {
        dispatch(setLocationLoader(true))
        console.log("error in fetching ethera locations", error)
      })
  }, [])

  //Fetching OTHER LOCATOINS to populate location dropdown
  useEffect(() => {
    if (providerState?.provider?.id) {
      dispatch(setLocationLoader(true))
      getOtherLocations(providerState?.provider?.id)
        .then((result: any) => {
          dispatch(setLocationLoader(false))
          dispatch(setOtherLocations(result?.data))
        })
        .catch((error: any) => {
          dispatch(setLocationLoader(false))
          console.log("error in fetching other locations", error)
        })
    }
  }, [providerState])

  useEffect(() => {
    if (
      appointmentState?.appointmentLocation !== "" &&
      appointmentState?.appointmentLocationType === "ethera"
    ) {
      dispatch(setLoader(true))
      let params = generateGetRoomsBody(appointmentState, providerState)
      getEtheraRooms(params)
        .then((result: any) => {
          dispatch(setEtheraRooms(result?.data))
          dispatch(setRoom({ label: "", value: "" }))

          dispatch(setLoader(false))
        })
        .catch((error: any) => {
          console.log("error in fetching ethera rooms", error)
          dispatch(setLoader(false))
        })
    }
  }, [
    appointmentState?.appointmentLocation,
    appointmentState?.bookingStartTime,
    appointmentState?.bookingEndTime,
    appointmentState?.appointmentDate,
    appointmentState?.selectedDatesArray,
  ])

  useEffect(() => {
    return () => {
      console.log("unmounts")
      dispatch(resetAppointmentLocationScreen())
    }
  }, [])

  //Fetching Room cost against each room selected
  useEffect(() => {
    if (appointmentState?.roomId) {
      let body = generateRoomCostBody(appointmentState)
      getRoomCost(body)
        .then((result: any) => {
          dispatch(setRoomCost(result?.data?.room_cost))
          console.log("result in room cost", JSON.stringify(result, null, 2))
        })
        .catch((error: any) => {
          console.log("error in room cost", JSON.stringify(error, null, 2))
        })
    }
  }, [appointmentState?.roomId])

  const LOCATIONDATA = MakeLocationData()

  const defaultDate = () => {
    let formatedDate = dayjs(new Date(date)).format("DD/MM/YYYY")
    dispatch(setAppointmentDate({ appointmentDate: formatedDate }))
    setDates((prev) => {
      return {
        ...prev,
        date: formatedDate,
        type: "",
        show: false,
      }
    })
    return formatedDate
  }

  return (
    <View style={[$container, $bottomContainerInsets]}>
      <MainHeader />
      <View style={styles.infoContainer}>
        <Text style={styles.infoText}>Appointment Location</Text>
      </View>
      <ScrollView
        style={{ flex: 1 }}
        contentContainerStyle={{ paddingHorizontal: 20, paddingBottom: 100 }}
      >
        <View style={{ paddingVertical: 5 }}>
          <Text style={styles.label}>Location</Text>
          {loadingState?.locationLoader && !LOCATIONDATA?.length? (
            <View style={styles.container}>
              <ActivityIndicator color={colors.orange} />
            </View>
          ) : (
            <SelectOptionButton
              selectedText={
                appointmentState?.appointmentLocation !== ""
                  ? appointmentState?.appointmentLocation
                  : "Location"
              }
              onPress={() => {
                setLocationDropdown(!locationDropdown)
              }}
              icon={<Ionicons name="location-outline" size={scale(20)} color="black" />}
            />
          )}

          {locationDropdown ? (
            <Animated.View
              entering={FadeIn.duration(200).easing(Easing.ease)}
              exiting={FadeOut.duration(200).easing(Easing.ease)}
              style={styles.locationView}
            >
              <SectionList
                sections={LOCATIONDATA??[]}
                keyExtractor={(item, index) => `key-${index}`}
                renderItem={({ item }: any) => {
                  return (
                    <TouchableOpacity
                      style={styles.locationItem}
                      onPress={() => onPressLocation(item)}
                    >
                      <View>
                        <Text style={{ color: colors.black }}>{item?.name}</Text>
                      </View>
                    </TouchableOpacity>
                  )
                }}
                renderSectionHeader={({ section: { title, checkLength } }) =>
                  checkLength && <Text style={styles.locationTitle}>{title}</Text>
                }
              />
            </Animated.View>
          ) : null}
          {appointmentState?.error && !appointmentState?.appointmentLocation ? (
            <Text style={{ color: "red", marginTop: scale(2) }}>
              Location {appointmentState?.error}
            </Text>
          ) : null}
        </View>
        <View style={{ paddingVertical: 5 }}>
          <Text style={styles.label}>Date</Text>
          <SelectOptionButton
            selectedText={dates?.date !== "" ? appointmentState?.appointmentDate : defaultDate()}
            onPress={() => {
              setDates((prev) => {
                return {
                  ...prev,
                  type: "date",
                  show: !prev?.show,
                }
              })
            }}
            icon={<AntDesign name="calendar" size={scale(20)} color="black" />}
          />
          {appointmentState?.error && !appointmentState?.appointmentDate ? (
            <Text style={{ color: "red", marginTop: scale(2) }}>
              Date {appointmentState?.error}
            </Text>
          ) : null}
        </View>

        <AppointmentRepeatView
          onPressWeekCheckBox={onPressWeekCheckBox}
          onPressDateCheckBox={onPressDateCheckBox}
          onPressRepeatGap={onPressRepeatGap}
          onPressRepeat={onPressRepeat}
          onSelectDates={onSelectDates}
          dateCheckBox={appointmentState?.dateCheckBox}
          weekCheckbox={appointmentState?.weeklyCheckbox}
          error={appointmentState?.error}
        />
        {appointmentState?.appointmentLocationType === "ethera" && (
          <>
            <View style={{ paddingVertical: 5, flexDirection: "row" }}>
              <View style={{ flex: 1, marginRight: 5 }}>
                <Text style={styles.label}>Start Time</Text>
                <SelectOptionButton
                  selectedText={
                    appointmentState?.bookingStartTime
                      ? appointmentState?.bookingStartTime
                      : "Start Time"
                  }
                  onPress={() => {
                    appointmentState?.bookingEndTime !== "" && dispatch(setBookingEndTime(""))
                    setDates((prev) => {
                      return {
                        ...prev,
                        type: "start",
                        show: true,
                      }
                    })
                  }}
                  icon={<AntDesign name="calendar" size={24} color="black" />}
                />
              </View>
              <View style={{ flex: 1, marginLeft: 5 }}>
                <Text style={styles.label}>End Time</Text>
                <SelectOptionButton
                  selectedText={
                    appointmentState?.bookingEndTime ? appointmentState?.bookingEndTime : "End Time"
                  }
                  onPress={() =>
                    setDates((prev) => {
                      return {
                        ...prev,
                        type: "end",
                        show: !prev?.show,
                      }
                    })
                  }
                  icon={<AntDesign name="calendar" size={24} color="black" />}
                />
              </View>
            </View>
            {appointmentState?.error &&
            (!appointmentState?.bookingStartTime || !appointmentState?.bookingEndTime) ? (
              <Text style={{ color: "red", marginTop: scale(2) }}>
                Time {appointmentState?.error}
              </Text>
            ) : null}
          </>
        )}

        {appointmentState?.appointmentLocationType === "ethera" && (
          <View style={{ paddingVertical: 5 }}>
            <Text style={styles.label}>Rooms</Text>
            {loadingState?.loader ? (
              <View style={styles.container}>
                <ActivityIndicator color={colors.orange} />
              </View>
            ) : (
              <>
                {appointmentState?.etheraRooms?.length !== 0 ? (
                  <DropdownComponent
                    search
                    searchPlaceholder="Search Room"
                    placeholder="Search Room"
                    onChange={(text) => {
                      dispatch(setRoom({ room: text }))
                    }}
                    data={appointmentState?.etheraRooms?.map(
                      (room: { name: string; id: string }) => ({
                        label: room?.name,
                        value: room?.id,
                      }),
                    )}
                    value={appointmentState?.roomId}
                  />
                ) : (
                  <EmptyComponent title="No Rooms Found" />
                )}
              </>
            )}
            {appointmentState?.error && !appointmentState?.room ? (
              <Text style={{ color: "red", marginTop: scale(2) }}>
                Room {appointmentState?.error}
              </Text>
            ) : null}
            <View style={styles.roomCost}>
              <Text style={styles.costLabel}>Room Cost</Text>
              <View style={styles.roomCostView}>
                <Text style={styles.roomCostText}>$</Text>
                <Text style={styles.roomCostText}>{appointmentState?.roomCost}</Text>
              </View>
            </View>
          </View>
        )}

        <View style={{ marginVertical: 44 }}>
          {appointmentState?.appointmentLoader === true ? (
            <View style={styles.btn}>
              <ActivityIndicator color={colors.orange} />
            </View>
          ) : (
            <Button preset="filled" text="Next" onPress={onNextPress} />
          )}

          <Button
            text="Back"
            textStyle={{ color: colors.brown }}
            onPress={() => navigation.goBack()}
          />
        </View>
      </ScrollView>
      <DatePicker
        locale="en"
        modal
        mode={dates.type === "date" ? "date" : "time"}
        open={dates.show}
        date={date}
        minuteInterval={15}
        minimumDate={(dates.type === "end" && minimumTime) || (dates.type === "date" && new Date())}
        onConfirm={(date) => {
          let formatedDate = dayjs(new Date(date)).format("DD/MM/YYYY")
          let formatedTime = dayjs(new Date(date)).format("h:mm A")
          if (dates.type === "date") {
            dispatch(setAppointmentDate({ appointmentDate: formatedDate }))
            setDates((prev) => {
              return {
                ...prev,
                date: formatedDate,
                type: "",
                show: false,
              }
            })
          }

          if (dates.type === "start") {
            dispatch(setBookingStartTime({ bookingStartTime: formatedTime }))
            setMinimunTime(date)
            setDates((prev) => {
              return {
                ...prev,
                start: formatedTime, //formatedDate,
                type: "",
                show: false,
              }
            })
          }

          if (dates.type === "end") {
            dispatch(setBookingEndTime({ bookingEndTime: formatedTime }))
            setMaximumTime(date)
            setDates((prev) => {
              return {
                ...prev,
                end: formatedTime, //formatedDate,
                type: "",
                show: false,
              }
            })
          }

          setDate(date)
        }}
        onCancel={() => {
          setDates((prev) => {
            return {
              ...prev,
              show: false,
            }
          })
        }}
      />
    </View>
  )
}

const $container: ViewStyle = {
  flex: 1,
  backgroundColor: colors.background,
}
